package com.sskj.gateway.service.impl;

import com.sskj.common.constant.RedisConstant;
import com.sskj.common.dto.EncodedCommand;
import com.sskj.common.util.StrUtil;
import com.sskj.common.vo.req.DeviceCommandReq;
import com.sskj.gateway.protocol.ProtocolRegistry;
import com.sskj.gateway.service.IDeviceCommandService;
import com.sskj.gateway.session.DeviceSession;
import com.sskj.gateway.session.DeviceSessionManager;
import com.sskj.protocol.IProtocol;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Slf4j
@Service("tcp")
public class DeviceTcpCommandService implements IDeviceCommandService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ProtocolRegistry protocolRegistry;

    @Autowired
    private DeviceSessionManager deviceSessionManager;

    @Override
    public EncodedCommand send(DeviceCommandReq commandReq) {
        // 获取对应的解析包
        // 获取设备CODE绑定的通信协议CODE，获取到指定的通信协议包实例
        String deviceProtocolKey = RedisConstant.DEVICE_PROTOCOL_MAPPING + commandReq.getDeviceCode();
        String deviceProtocolCode = stringRedisTemplate.opsForValue().get(deviceProtocolKey);
        if (StrUtil.isBlank(deviceProtocolCode)) {
            log.warn("设备 {} 未绑定任何通信协议", commandReq.getDeviceCode());
            throw new RuntimeException("设备未绑定任何通信协议");

        }

        // 获取设备绑定对应的通信协议实例
        IProtocol protocol = protocolRegistry.getProtocol(deviceProtocolCode);
        EncodedCommand encodedCommand = protocol.encode(commandReq);

        DeviceSession session = deviceSessionManager.getSession(commandReq.getDeviceCode());
        if (session == null) {
            log.warn("设备 {} 未连接会话", commandReq.getDeviceCode());
            throw new RuntimeException("设备未连接会话");
        }

        Channel channel = (Channel)session.getChannel();
        channel.writeAndFlush(Unpooled.wrappedBuffer(encodedCommand.getRawBytes()));
        return encodedCommand;
    }
}
